
#ifndef	PHYSICS_USER_DATA_HPP
#define	PHYSICS_USER_DATA_HPP

#include <physics/physics.hpp>
#include <physics/collision_message/collision_message.hpp>
#include <set>

class base_user_data
{
public:

	virtual ~base_user_data( ) { };

	body_ptr body( ) const
	{
		return m_weak_body.lock( );
	}

	virtual void on_contact( b2Contact * contact, base_user_data * /*self_user_data*/, base_user_data * other_user_data ) = 0;

protected:

	base_user_data( body_weak_ptr body )
		:		m_weak_body( body )
	{}

	body_weak_ptr m_weak_body;
};

class fire_event_user_data : public base_user_data
{
public:

	fire_event_user_data( body_weak_ptr body )
		:		base_user_data( body )
	{}

	void on_contact( b2Contact * contact, base_user_data * /*self_user_data*/, base_user_data * other_user_data )
	{
		body_ptr other_body = other_user_data != nullptr ? other_user_data->body( ) : body_ptr( );

		std::for_each( m_messages.cbegin( ), m_messages.cend( ), [&other_body, this]( std::string const & message )
		{
			g_messenger.push( collision_message::name( ), message_data_ptr( new collision_message( message, body( ), other_body ) ) );
		} );
	}

	void add_message( std::string const & message )
	{
		m_messages.insert( message );
	}

private:

	typedef std::set< std::string > message_set_t;

	message_set_t m_messages;
};

#endif	//PHYSICS_USER_DATA_HPP
